//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_project"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectApiImpl) AddTag(ctx context.Context, req *project_api.AddTagRequest) (*project_api.AddTagResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_api.AddTagResponse{
			Code:   project_api.AddTagResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_api.AddTagResponse{
			Code:   project_api.AddTagResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_api.AddTagResponse{
			Code:   project_api.AddTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if projectItem.Closed {
		return &project_api.AddTagResponse{
			Code:   project_api.AddTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_api.AddTagResponse{
			Code:   project_api.AddTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	tagId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_dao.TagInfoDao.Insert(sessCtx, &project_dao.TagInfoDbItem{
			TagId:             tagId,
			ProjectId:         req.ProjectId,
			TagName:           req.TagName,
			CreateTime:        nowTime,
			BgColor:           req.BgColor,
			UseInTask:         req.UseInTask,
			UseInBug:          req.UseInBug,
			UseInReq:          req.UseInReq,
			UseInSpritSummary: req.UseInSpritSummary,
			UseInEntry:        req.UseInEntry,
		})
		if err != nil {
			return nil, err
		}
		return &project_api.AddTagResponse{
			Code:  project_api.AddTagResponse_CODE_OK,
			TagId: tagId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_project.AddTagNotice{
		ProjectId: req.ProjectId,
		TagId:     tagId,
	})
	return ret.(*project_api.AddTagResponse), nil
}

func (apiImpl *ProjectApiImpl) UpdateTag(ctx context.Context, req *project_api.UpdateTagRequest) (*project_api.UpdateTagResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_api.UpdateTagResponse{
			Code:   project_api.UpdateTagResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_api.UpdateTagResponse{
			Code:   project_api.UpdateTagResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_api.UpdateTagResponse{
			Code:   project_api.UpdateTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if projectItem.Closed {
		return &project_api.UpdateTagResponse{
			Code:   project_api.UpdateTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_api.UpdateTagResponse{
			Code:   project_api.UpdateTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := project_dao.TagInfoDao.Exist(ctx, req.ProjectId, req.TagId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_api.UpdateTagResponse{
			Code:   project_api.UpdateTagResponse_CODE_NO_TAG,
			ErrMsg: "标签不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_dao.TagInfoDao.Update(sessCtx, &project_dao.TagInfoDbItem{
			TagId:             req.TagId,
			ProjectId:         req.ProjectId,
			TagName:           req.TagName,
			CreateTime:        nowTime,
			BgColor:           req.BgColor,
			UseInTask:         req.UseInTask,
			UseInBug:          req.UseInBug,
			UseInReq:          req.UseInReq,
			UseInSpritSummary: req.UseInSpritSummary,
			UseInEntry:        req.UseInEntry,
		})
		if err != nil {
			return nil, err
		}
		return &project_api.UpdateTagResponse{
			Code: project_api.UpdateTagResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_project.UpdateTagNotice{
		ProjectId: req.ProjectId,
		TagId:     req.TagId,
	})
	return ret.(*project_api.UpdateTagResponse), nil
}

func (apiImpl *ProjectApiImpl) RemoveTag(ctx context.Context, req *project_api.RemoveTagRequest) (*project_api.RemoveTagResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_api.RemoveTagResponse{
			Code:   project_api.RemoveTagResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_api.RemoveTagResponse{
			Code:   project_api.RemoveTagResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_api.RemoveTagResponse{
			Code:   project_api.RemoveTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if projectItem.Closed {
		return &project_api.RemoveTagResponse{
			Code:   project_api.RemoveTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_api.RemoveTagResponse{
			Code:   project_api.RemoveTagResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := project_dao.TagInfoDao.Exist(ctx, req.ProjectId, req.TagId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_api.RemoveTagResponse{
			Code:   project_api.RemoveTagResponse_CODE_NO_TAG,
			ErrMsg: "标签不存在",
		}, nil
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_dao.TagInfoDao.Remove(sessCtx, req.ProjectId, req.TagId)
		if err != nil {
			return nil, err
		}
		return &project_api.RemoveTagResponse{
			Code: project_api.RemoveTagResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_project.RemoveTagNotice{
		ProjectId: req.ProjectId,
		TagId:     req.TagId,
	})
	return ret.(*project_api.RemoveTagResponse), nil
}

func (apiImpl *ProjectApiImpl) ListTag(ctx context.Context, req *project_api.ListTagRequest) (*project_api.ListTagResponse, error) {
	emptyList := []*project_api.TagInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_api.ListTagResponse{
			Code:        project_api.ListTagResponse_CODE_WRONG_SESSION,
			ErrMsg:      "会话不存在",
			TagInfoList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_api.ListTagResponse{
			Code:        project_api.ListTagResponse_CODE_NO_PROJECT,
			ErrMsg:      "项目不存在",
			TagInfoList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_api.ListTagResponse{
			Code:        project_api.ListTagResponse_CODE_NO_PERMISSION,
			ErrMsg:      "没有权限",
			TagInfoList: emptyList,
		}, nil
	}

	tagItemList, err := project_dao.TagInfoDao.List(ctx, req.ProjectId, req.TagScopeType)
	if err != nil {
		return nil, err
	}
	infoList := []*project_api.TagInfo{}
	for _, tagItem := range tagItemList {
		infoList = append(infoList, tagItem.ToTagInfo())
	}
	return &project_api.ListTagResponse{
		Code:        project_api.ListTagResponse_CODE_OK,
		TagInfoList: infoList,
	}, nil
}
